home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / csim / source.lha / source / Threads / GnuThreads / gnulwp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-14  |  5.1 KB  |  245 lines

  1. /*
  2.  * lwp.c -- lightweight process creation, destruction and manipulation.
  3.  * Copyright (C) 1991 Stephen Crane.
  4.  *
  5.  * This is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 1, or (at your option)
  8.  * any later version.
  9.  *
  10.  * This software is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * see the file COPYING.  If not, write to
  17.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  * author: Stephen Crane, (jsc@doc.ic.ac.uk), Department of Computing,
  20.  * Imperial College of Science, Technology and Medicine, 180 Queen's
  21.  * Gate, London SW7 2BZ, England.
  22.  */
  23.  
  24. #include <setjmp.h>
  25. #include <malloc.h>
  26. #include <signal.h>
  27. #include <stdio.h>
  28.  
  29. #include "gnulwp.h"
  30.  
  31. struct lpq schedq[MAXPRI], deadq;
  32. struct pcb *currp;
  33. int maxpri=0;        /* maximum priority so far */
  34.  
  35. static int oldmask;
  36. static int growsdown (void *x) { int y; return x > (void *)&y; }
  37.  
  38. /*
  39.  * creatp -- create a process.
  40.  */
  41. struct pcb *creatp (int priority, void (*entry)(int, char**, void*), int size,
  42.             int argc, char **argv, void *envp)
  43. {
  44.     struct pcb *newp;
  45.     int *stack, x;
  46.     extern struct pcb *currp;
  47.  
  48.     if (!(newp = (struct pcb *)malloc (sizeof(struct pcb))))
  49.         return (0);
  50.     size += sizeof(stkalign_t);
  51.     if (!(stack = (int *)malloc (size)))
  52.         return (0);
  53.     newp->entry = entry;
  54.     newp->argc = argc;
  55.     newp->argv = argv;
  56.     newp->envp = envp;
  57.     newp->context[0] = growsdown (&x)? (size+(int)stack) & -sizeof(stkalign_t): (int)stack;
  58.     if (MAXPRI <= priority)
  59.         priority = MAXPRI-1;
  60.     if (maxpri < (newp->pri = priority))
  61.         maxpri = priority;
  62.     newp->sbtm = stack;
  63.     newp->size = size;
  64.     newp->dead = 0;
  65.     readyp (newp);
  66.     readyp (currp);
  67.     initp (newp);        /* architecture-dependent */
  68.     reschedp ();
  69.     return (newp);
  70. }
  71.  
  72. /*
  73.  * readyp -- put process on ready queue.  if null, assume current.
  74.  */
  75. void readyp (struct pcb *p)
  76. {
  77.     extern struct pcb *currp;
  78.     extern struct lpq schedq[];
  79.  
  80.     if (!p)
  81.         p = currp;
  82.     toq (&schedq[p->pri], p);
  83. }
  84.  
  85. /*
  86.  * getenvp -- return back pointer to user's data
  87.  */
  88. void *getenvp (struct pcb *p)
  89. {
  90.     if (!p)
  91.         p = currp;
  92.     return (p->envp);
  93. }
  94.  
  95. /*
  96.  * reschedp -- schedule another process.  we also check for dead
  97.  * processes here and free them.
  98.  */
  99. void reschedp ()
  100. {
  101.     extern struct lpq schedq[];
  102.     struct pcb *nextp;
  103.     int i;
  104.  
  105.     for (i=maxpri+1; i--; )
  106.     {
  107.         while (nextp = hoq (&schedq[i]))
  108.             if (nextp->dead) {
  109.                 free (nextp->sbtm);
  110.                 free (nextp);
  111.                 if (nextp==currp)
  112.                     currp = 0;
  113.             } else
  114.                 goto change;
  115.         }
  116. change:
  117.     /* change context? ... save current context */
  118.     if (currp != nextp && !(currp && savep (currp->context))) {
  119.         /* restore previous context */
  120.         currp = nextp;
  121.         restorep (currp->context);
  122.     }
  123. }
  124.  
  125. /*
  126.  * yieldp -- yield the processor to another thread.
  127.  */
  128. void yieldp (void)
  129. {
  130.     readyp (currp);
  131.     reschedp ();
  132. }
  133.  
  134. /*
  135.  * suicidep -- cause the current process to be scheduled for deletion.
  136.  */
  137. void suicidep (void)
  138. {
  139.     currp->dead = 1;
  140.     yieldp ();
  141. }
  142.  
  143. /*
  144.  * destroyp -- mark a process as dead, so it will never be rescheduled.
  145.  */
  146. void destroyp (struct pcb *p)
  147. {
  148.     p->dead = 1;
  149. }
  150.  
  151. /*
  152.  * nullp -- a null process, always ready to run.
  153.  * it (1) sets its priority to maximum to prevent a signal doing a
  154.  * reschedule (2) enables signals, waits for one and handles it
  155.  * and (3) resets its priority causing a reschedule.
  156.  */
  157.  
  158. static void nullp (int dummy1 = 0, char** dummy2 = 0, void* dummy3 = 0)
  159. {
  160.     for (;;) {
  161.         int p = prisetp (MAXPRI-1);
  162.         sigpause (oldmask);
  163.         prisetp (p);
  164.     }
  165. }
  166.  
  167. /*
  168.  * prisetp -- set the thread's priority, returning the old.
  169.  * if the new priority is lower than the old, we reschedule.
  170.  */
  171. int prisetp (int new_p)
  172. {
  173.     int old = currp->pri;
  174.  
  175.     if (MAXPRI <= new_p)
  176.         new_p = MAXPRI-1;
  177.     if (maxpri < new_p)
  178.         maxpri = new_p;
  179.     currp->pri = new_p;
  180.     if (new_p < old)
  181.         yieldp ();
  182.     return (old);
  183. }
  184.  
  185. /*
  186.  * initlp -- initialise the coroutine structures
  187.  */
  188. struct pcb *initlp (int pri)
  189. {
  190.     extern struct lpq schedq[];
  191.     extern struct pcb *currp;
  192.     struct lpq *q;
  193.     int i, *stack;
  194.     struct sigvec s;
  195.  
  196.     if (!(currp = (struct pcb *)malloc (sizeof (struct pcb))))
  197.         return (0);
  198.     if (!(stack = (int *)malloc (64)))
  199.         return (0);
  200.     if (MAXPRI <= pri)
  201.         pri = MAXPRI-1;
  202.     if (maxpri < pri)
  203.         maxpri = pri;
  204.     currp->next = 0;
  205.     currp->sbtm = stack;    /* dummy stack */
  206.     currp->pri = pri;
  207.     currp->dead = 0;
  208.  
  209.     for (i=MAXPRI, q=schedq; i--; q++)
  210.         q->head = q->tail = 0;
  211.     deadq.head = deadq.tail = 0;
  212.  
  213.     s.sv_handler = onalarm;
  214.     s.sv_flags = SV_INTERRUPT;
  215.     s.sv_mask = 0;
  216.     sigvec (SIGALRM, &s, (struct sigvec *)0);
  217.  
  218.     oldmask = sigsetmask (SIGNALS);
  219.     creatp (0, nullp, 8192, 0, 0, 0);
  220.     return (currp);
  221. }
  222.  
  223. /*
  224.  * wrapp -- process entry point.
  225.  */
  226. void wrapp (void)
  227. {
  228.     extern struct pcb *currp;
  229.  
  230.     sigsetmask (SIGNALS);
  231.     (*currp->entry) (currp->argc, currp->argv, currp->envp);
  232.     suicidep ();
  233. }
  234.  
  235. /* access operations for modula-2 */
  236. int btmcurrp (void)
  237. {
  238.     return ((int)currp->sbtm);
  239. }
  240.  
  241. int sizecurrp (void)
  242. {
  243.     return (currp->size);
  244. }
  245.